﻿using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using JTLeigh.Commerce.Spencer.Core.Common;

namespace JTLeigh.Commerce.Spencer.Core.Testing
{

	/// <summary>
	/// <see langword="static" /> methods for performing serialization tests.
	/// </summary>
	public static class SerializationTestTools
	{

		/// <summary>
		/// Serializes the specified object to an in-memory stream using binary serialization, 
		/// deserializes the stream, and returns the resulting object.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This method is used in to ensure serializable objects can be serialized and 
		/// deserialized correctly.
		/// </para>
		/// </remarks>
		/// <typeparam name="TObject">The type of the <paramref name="source"/> object.</typeparam>
		/// <param name="source">The source <typeparamref name="TObject"/> object.</param>
		/// <returns>The resulting <typeparamref name="TObject"/> object.</returns>
		public static TObject BinarySerializeDeserialize<TObject>(TObject source)
		{
			MemoryStream stream;
			BinaryFormatter formatter;
			TObject resulting;

			Safety.AssertArgumentNotNull("source", source);

			stream = new MemoryStream();
			formatter = new BinaryFormatter();
			formatter.Serialize(stream, source);
			stream.Position = 0;
			resulting = (TObject)formatter.Deserialize(stream);
			return resulting;
		}

		/// <summary>
		/// Serializes the specified object to an in-memory stream using data contract 
		/// serialization, deserializes the stream, and returns the resulting object.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This method is used in to ensure data contracts can be serialized and deserialized
		/// correctly.
		/// </para>
		/// </remarks>
		/// <typeparam name="TObject">The type of the <paramref name="source"/> object.</typeparam>
		/// <param name="source">The source <typeparamref name="TObject"/> object.</param>
		/// <returns>The resulting <typeparamref name="TObject"/> object.</returns>
		public static TObject DataContractSerializeDeserialize<TObject>(TObject source)
		{
			MemoryStream stream;
			DataContractSerializer serializer;
			TObject resulting;

			Safety.AssertArgumentNotNull("source", source);

			stream = new MemoryStream();
			serializer = new DataContractSerializer(typeof(TObject));
			serializer.WriteObject(stream, source);
			stream.Position = 0;
			resulting = (TObject)serializer.ReadObject(stream);
			return resulting;
		}

	}

}
